package qc.module.qms.api.consumer;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import qc.common.core.constants.QmsMQConstant;
import qc.common.core.enums.qms.QmsDataFlowOperateTypeEnum;
import qc.common.core.enums.qms.QmsPointTimeSegmentEnum;
import qc.common.core.utils.IdentifierUtil;
import qc.common.core.utils.QmsTimeUtil;
import qc.module.qms.algorithm.NumericCalc.dto.QmsNumericCalcUseMethod;
import qc.module.qms.dto.calc.QmsPointDataCalcJudgeResultDto;
import qc.module.qms.dto.calc.QmsPointDataCalcSaveResultDto;
import qc.module.qms.dto.mq.QmsMqManualTaskCalcPointDataMessageDto;
import qc.module.qms.dto.task.ManualTaskOperateResultDto;
import qc.module.qms.entity.QmsPoint;
import qc.module.qms.service.QmsBasicConfigCacheGetService;
import qc.module.qms.service.QmsManualTaskService;
import qc.module.qms.service.calc.QmsNumericCalcGetService;
import qc.module.qms.service.pointdata.QmsPointDataCalcService;
import qc.module.qms.service.pointdata.QmsPointDataLatestService;

import java.time.LocalDateTime;

/**
 * 人工长耗时任务--点号数据计算/处理消费者Consumer
 *
 * @author QuCheng Tech
 * @since 2025/10/26
 */
@Component
@RocketMQMessageListener(
        topic = QmsMQConstant.MQ_MANUALTASK_CALCPOINTDATA_TOPIC,
        consumerGroup = QmsMQConstant.MQ_MANUALTASK_CALCPOINTDATA_CONSUMER_GROUP
)
public class ManualTaskCalcPointDataConsumer implements RocketMQListener<QmsMqManualTaskCalcPointDataMessageDto> {
    private static final Logger logger = LoggerFactory.getLogger(ManualTaskCalcPointDataConsumer.class);

    @Autowired
    private QmsManualTaskService manualTaskService;

    @Autowired
    private QmsBasicConfigCacheGetService basicConfigCacheGetService;

    @Autowired
    private QmsPointDataCalcService pointDataCalcService;

    @Autowired
    private QmsNumericCalcGetService numericCalcGetService;

    @Autowired
    private QmsPointDataLatestService pointDataLatestService;

    @Override
    public void onMessage(QmsMqManualTaskCalcPointDataMessageDto message) {
        if (message == null) {
            logger.info("onMessage 计算点号数据人工任务消息处理，消息对象为null");
        } else {
            String wbsid = message.getWbsid();
            String pointid = message.getPointid();
            QmsPointTimeSegmentEnum tmseg = message.getTmseg();

            logger.info("onMessage 计算点号数据人工任务消息处理，WBSID[" + wbsid + "]，点号ID[" + pointid + "]，点号名称[" + message.getPointname() +
                    "]，时段类型[" + tmseg + "]，计算时间段[" + QmsTimeUtil.format(message.getBegintm(), tmseg) + "]-[" + QmsTimeUtil.format(message.getTendtm(), tmseg) + "]");

            //只要进入处理方法，先设置计算点号数据WBS的状态为开始执行
            ManualTaskOperateResultDto startWbsResult = manualTaskService.startWbsExecute(wbsid);
            if (startWbsResult.isSuccess() == true) {
                logger.debug("onMessage 计算点号数据人工任务消息处理，WBSID[" + wbsid + "]，设置任务WBS开始执行成功");
            } else {
                //设置任务WBS为开始执行失败，记录日志
                logger.warn("onMessage 计算点号数据人工任务消息处理，WBSID[" + wbsid + "]，设置任务WBS开始执行失败，错误信息[" + startWbsResult.getMsg() + "]");
            }

            //计算点号数据人工任务WBS执行结果初始化
            boolean success = false;
            String executeResult = null;

            try {
                QmsPoint point = basicConfigCacheGetService.getPoint(pointid);
                if (point == null) {
                    executeResult = "根据点号[" + pointid + "]获取到的点号对象为null";
                    logger.warn(executeResult);
                } else {
                    //需要先判断点号是否有计算方法，如果没有计算方法不进行计算；如果不先判断是否有计算方法会在计算中生成错误日志
                    QmsNumericCalcUseMethod calcMethod = numericCalcGetService.getPointValidCalcUseMethod(point, tmseg);
                    if (calcMethod == null) {
                        executeResult = "计算点号[" + pointid + "]，时段类型[" + tmseg + "]，无有效的计算方法，不进行人工任务点号数据计算";
                        logger.warn(executeResult);
                    } else {
                        //点号有计算方法，判断和处理本次计算的时间；如果人工任务中指定的计算时间段超过定时计算的不需要进行计算；
                        QmsPointDataCalcJudgeResultDto judgeResult = numericCalcGetService.getManualTaskCalcPointDataJudgeResult(point, tmseg, calcMethod, message.getBegintm(), message.getTendtm());
                        if (judgeResult == null) {
                            logger.warn("计算点号[" + pointid + "]，时段类型[" + tmseg + "]，判断本次计算时段结果为空，不进行人工任务点号数据计算");
                        } else {
                            if (judgeResult.isNeedCalc() == false) {
                                //不需要计算
                                logger.info("计算点号[" + pointid + "]，时段类型[" + tmseg + "]，判断本次不需要进行人工任务点号数据计算，判断结果信息[" + judgeResult.getMsg() + "]");
                            } else {
                                //需要计算，判断是否有msg，有的话进行日志记录（可能会有对计算时间段进行自动修订设置）
                                //获取判定后得到的计算起止时间
                                LocalDateTime calcBeginPeriodTime = judgeResult.getCalcBeginPeriodTime();
                                LocalDateTime calcEndPeriodTime = judgeResult.getCalcEndPeriodTime();
                                if (StringUtils.isNotBlank(judgeResult.getMsg()))
                                    logger.info("计算点号[" + pointid + "]，时段类型[" + tmseg + "]，判断本次进行人工任务点号数据计算时间段为[" +
                                            QmsTimeUtil.format(calcBeginPeriodTime, tmseg) + "]-[" + QmsTimeUtil.format(calcEndPeriodTime, tmseg)
                                            + "]，判断结果信息[" + judgeResult.getMsg() + "]");
                                else
                                    logger.debug("计算点号[" + pointid + "]，时段类型[" + tmseg + "]，判断本次进行人工任务点号数据计算时间段为[" +
                                            QmsTimeUtil.format(calcBeginPeriodTime, tmseg) + "]-[" + QmsTimeUtil.format(calcEndPeriodTime, tmseg) + "]");

                                //对每个点号计算生成一个全局的流程ID，同时也作为节点ID
                                String flowid = IdentifierUtil.simpleUUID();
                                //调用计算方法，在pointDataCalcService.calc方法中已经完成日志记录、流程日志消息发送、原始数据处理标记修改
                                //此处可以不对处理结果进行判断和输出显示
                                //调用计算点号方法中设置人工标记为true，optype为人工操作的进行点号数据计算
                                QmsPointDataCalcSaveResultDto calcSaveResultDto = pointDataCalcService.calcPointDatas(point, tmseg, calcMethod,
                                        calcBeginPeriodTime, calcEndPeriodTime, QmsDataFlowOperateTypeEnum.CALC_POINT_DATA_BY_MANUAL, true, flowid, flowid);

                                //计算完成后更新点号的最新定时计算时段
                                pointDataLatestService.updateCalcDataTime(pointid, tmseg, judgeResult.getCalcEndPeriodTime(), false);
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                executeResult = "" + ex.getMessage();
            }

            //计算点号数据WBS执行结束，不管是否成功均在此更新任务WBS的状态和执行结果信息
            ManualTaskOperateResultDto endWbsResult = manualTaskService.endWbsExecute(wbsid, success, executeResult);
            if (endWbsResult.isSuccess() == true) {
                logger.debug("onMessage 计算点号数据人工任务消息处理，WBSID[" + wbsid + "]，设置任务WBS结束执行成功");
            } else {
                //设置任务WBS为开始执行失败，记录日志
                logger.warn("onMessage 计算点号数据人工任务消息处理，WBSID[" + wbsid + "]，设置任务WBS结束执行失败，错误信息[" + endWbsResult.getMsg() + "]");
            }
        }
    }
}
